home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / adikit.arc / DSHERC.C < prev    next >
C/C++ Source or Header  |  1986-12-01  |  21KB  |  619 lines

  1. /*      DSHERC.C
  2.  
  3.     Sample ADI device driver for use as model in driver development.
  4.  
  5.     Configurator and display driver for the Hercules display board on
  6.     the IBM PC.  Split-screen configuration.
  7.  
  8. */
  9.  
  10. /* #define DEBUG 1 */
  11.  
  12. /*  If DUMB is defined, this driver will act as a very stupid display
  13.     and make AutoCAD do all its tricks to restore things on mode
  14.     switches.  */
  15.  
  16. /* #define DUMB 1 */
  17.  
  18. /*  If SMART is defined, this driver will include test code to exercise
  19.     the "extended functions" SYNC and REDRAW.  It doesn't really do them.
  20.     It is imprudent to set both SMART and DUMB at the same time.  */
  21.  
  22. /* #define SMART 1 */
  23.  
  24. #include    <stdio.h>
  25.  
  26. #define VERSION     "1.10"
  27. #define REVDATE     "10/28/86"
  28. #define FALSE       0
  29. #define TRUE        1
  30.  
  31. /*   Default interrupt vector for display drivers is 0x7A.  This is
  32.      selectable by user during AutoCAD configuration.  */
  33.  
  34. #define VECTOR      0x7A              /* Interrupt vector used for messages */
  35.  
  36. #define YSIZE       348
  37. #define XSIZE       720
  38.  
  39. #define BASE6845    0x3B4             /* CRT controller base address. */
  40. #define ADRREG      BASE6845
  41. #define DATAREG     (BASE6845+1)
  42. #define CTLREG      (BASE6845+4)
  43. #define STATREG     (BASE6845+6)
  44. #define CFGREG      (BASE6845+11)     /* configuration register */
  45. #define INITL       14                /* Number of CRTC regs to initialize. */
  46. #define NSYNC       6                 /* Number of vsyncs to wait on mode switch */
  47. #define TEXTSEG     0xB000            /* vram base for text screen. */
  48. #define MCHARS      8                 /* Characters in a menu box. */
  49. #define CHARHGT     14                /* Character height in pixels. */
  50. #define CHARWID     9                 /* Character width. */
  51. #define XMENUMIN    (XSIZE-CHARWID*MCHARS) /* Left margin of menu box. */
  52. #define XMAX        (XMENUMIN-6)      /* Right margin of graphics area. */
  53. #define SPLIT       3                 /* Lines in split-text area. */
  54. #define SPLITHGT    (CHARHGT*SPLIT+7) /* Split-text area height. */
  55. #define YSPLIT      (YSIZE-SPLIT*CHARHGT) /* Row nr of text area */
  56. #define XCLINE      (9*40)            /* Start of coordinate display line. */
  57.  
  58. #define msb(v)            ((v >> 8) & 0xFF)
  59. #define lsb(v)            (v & 0xFF)
  60. #define packbyte(x, y)    ((x << 8) | y)
  61.  
  62. /*  BIOS interrupt numbers and subfunctions:  */
  63.  
  64. #define     VIDEO_IO    0x10
  65. #define     SCURSOR     2             /* Set cursor */
  66. #define     SCROLL_UP   6             /* Scroll active page up */
  67.  
  68. /*  Request codes  */
  69.  
  70. #define    INIT1     1                /* Initialise parameters 1 */
  71. #define    INIT2     2                /* Initialise parameters 2 */
  72. #define    INIT3     3                /* Initialise parameters 3 */
  73. #define    INIT4     4                /* Initialise parameters 4 */
  74. #define    INIT5     5                /* Initialise parameters 5 */
  75. #define    TERM      9                /* Terminate */
  76.  
  77. #define    CLEAR    10                /* Clear graphics screen */
  78. #define    DOT      11                /* Complement dot */
  79. #define    MOVE     12                /* Set screen cursor */
  80. #define    DRAW     13                /* Draw line */
  81. #define    FLOOD    14                /* Solid fill vertex / point */
  82. #define    MARK     15                /* Draw graphic cursor */
  83. #define    CMARK    16                /* Clear graphic cursor */
  84.  
  85. #define    CHAR     20                /* Draw character on graphics screen */
  86. #define    ECHAR    21                /* End character string */
  87. #define    MHLITE   22                /* Menu highlight */
  88. #define    MDHLITE  23                /* Menu de-highlight */
  89. #define    MNUCUR   24                /* Set character address to box */
  90.  
  91. #define    TPROMPT  30                /* Set character address to prompt line */
  92. #define    QPLOT    31                /* Screen dump */
  93. #define    RPEN     32                /* Read pen */
  94. #define    GOTEXT   33                /* Go to text screen */
  95. #define    GOTEXTU  34                /* Go to text screen - user request */
  96. #define    GOGRAPH  35                /* Go to graphics screen */
  97. #define    WRSPLIT  36                /* Write to split screen */
  98. #define    MODELINE 37                /* Write to mode line */
  99. #define    COORDL   38                /* Write to coordinate line */
  100.  
  101. #define    SYNC     50                /* Flush display buffers */
  102. #define    REDRAW   51                /* Driver-local redraw */
  103.  
  104. /*  Configuration bits  */
  105.  
  106. #define    CF_TEXT   1                /* Draw text scrolling area */
  107. #define    CF_MENU   2                /* Draw screen menu */
  108. #define    CF_STATUS 4                /* Draw status line */
  109.  
  110. /*  Repaint control bits  */
  111.  
  112. #define    RP_STAT   1                /* Repaint status line */
  113. #define    RP_MENU   2                /* Repaint status line */
  114. #define    RP_SCROLL 4                /* Repaint scroll area */
  115. #define    RP_GRAPH  8                /* Redraw picture */
  116.  
  117. /*  Driver mode bits  */
  118.  
  119. #define    DM_CCECH  1                /* Suppress echo of control C */
  120. #define    DM_HLEN   2                /* Driver can do highlighting */
  121. #define    DM_GROK   4                /* Driver is single screen */
  122.  
  123. /*  Extended function enable bits */
  124.  
  125. #define    EF_SYNC   1                /* Enable SYNC function */
  126. #define    EF_REDRAW 2                /* Enable REDRAW function */
  127.  
  128. /******  Global symbols exported (to DSHERCA)  ******/
  129.  
  130. short graphx, graphy;          /* Graphics area width and height. */
  131. short color;                          /* Current colour */
  132. short hilight;                        /* Highlight flag */
  133. short cline;                          /* Status line configured */
  134.  
  135. /******  Local stuff  ******/
  136.  
  137. /*  Initial values for CRTC registers R0-R13  */
  138. static char
  139.     graphinit[INITL] = {
  140.      56,45,48, 8,90,0,87,87,2, 3, 0, 0,0,0}
  141.     ,
  142.     textinit[INITL] =  {
  143.      97,80,82,15,25,6,25,25,2,13,0,14,0,0};
  144.  
  145. static short tcursx,tcursy;           /* Text cursor position */
  146. static int splitchar = 0,             /* Characters in current line. */
  147.                        splitline = YSPLIT, /* Line we're writing on. */
  148.                        splitdirty = 0;/* Any characters on line flag. */
  149. static short ybias;                   /* To convert shorts to hard coords. */
  150. static short notxt, nomnu;            /* Configuration status */
  151. static short ixdots, iydots, ixdotsm, modelinl, mnuchars,
  152.              maxboxes, hlenab, graphok, hwfill;
  153.  
  154. struct pregs {                        /* Structure to communicate with ACAD */
  155.     short code, arg1, arg2, arg3;
  156. };
  157. static struct pregs c;                /* Master communication structure */
  158.  
  159. extern char inp();
  160. unsigned r6845();
  161.  
  162. extern long _psp, _mnext;
  163. extern unsigned _tsize;
  164.  
  165. main(argc,argv)
  166.   int argc; 
  167.   char *argv[];
  168. {
  169.     short i, cl;
  170.     short lx, ly;
  171.  
  172. #ifdef DEBUG
  173.     printf("\n  Mnext = %08lx  _Psp = %08lx  _tsize = %04x",
  174.            _mnext, _psp, _tsize);
  175. #endif
  176.  
  177.     printf("\n--- Autodesk Device Interface/ADI Driver ---");
  178.  
  179. #ifdef DUMB
  180.     printf("\nDumb ADI graphics board driver Vers. %s installed as INT %03xh.",
  181. #else
  182.            printf("\nHercules Graphics Board driver Vers. %s installed as INT %03xh.",
  183. #endif
  184.             VERSION,VECTOR);
  185. #ifdef SMART
  186.            printf("\nSmart display debugging features enabled.");
  187. #endif
  188.  
  189.            printf("\nSample ADI Driver created %s by Autodesk, Inc.\n",REVDATE);
  190.  
  191.            /* ADI driver developer should include name of company, or company and
  192.               individual, responsible for creation of ADI device driver and date
  193.               of driver creation to aid in identifying driver. */
  194.  
  195.            while (TRUE) {
  196.             iwait(VECTOR, &c, &c);
  197.  
  198.             /* Dispatch commands received from active program */
  199.  
  200. #ifdef DUMPCMD
  201.             if (c.code != 32) {       /* Skip pen probes */
  202.              if (c.code == 20 || c.code == 36)
  203.              putchar(c.arg1);
  204.              else
  205.              printf("\n ** Display(%d):  %d, %d, %d **",
  206.               c.code, c.arg1, c.arg2, c.arg3);
  207.             }
  208. #endif
  209.  
  210.             switch (c.code) {
  211.  
  212.              case INIT1:
  213.              notxt = !(c.arg1 & CF_TEXT);
  214.              nomnu = !(c.arg1 & CF_MENU);
  215.              cline = !!(c.arg1 & CF_STATUS);
  216.              ixdotsm = XSIZE - 1;
  217.              ixdots = nomnu ? XSIZE - 1 : XMAX;
  218.              graphx = (ixdots + 1);   /* Graphics area width.  */
  219.  
  220.              /*  YBIAS:  "natural" y-coordinate of screen coord origin.  Also
  221.           number of pixels vertically in menu area.  */
  222.  
  223.              ybias = iydots = notxt ? YSIZE - 1 : YSIZE - 1 - SPLITHGT;
  224.              if (cline)
  225.              iydots -= CHARHGT;       /* Status line correction. */
  226.              modelinl = XCLINE/9;     /* Mode line length. */
  227.              graphy = iydots + 1;     /* Graphics area height. */
  228.              mnuchars = MCHARS;
  229.              maxboxes = nomnu ? 0 : (ybias+1) / CHARHGT;
  230.              hwfill = 0;              /* No hardware fill */
  231.              hlenab = 1;              /* Driver knows how to highlight */
  232.              graphok = 1;             /* Graphics mode ok now. */
  233.  
  234.              c.code = TRUE;
  235.              c.arg1 = ixdots;
  236.              c.arg2 = iydots;
  237.              c.arg3 = ixdotsm;
  238.              break;
  239.  
  240.              case INIT2:
  241.              c.arg1 = packbyte(modelinl, mnuchars);
  242. #ifdef DUMB
  243.              c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK | DM_CCECH);
  244. #else
  245.              c.arg2 = packbyte(maxboxes, DM_HLEN | DM_GROK);
  246. #endif
  247.              c.arg3 = packbyte(SPLIT, hwfill);
  248.              break;
  249.  
  250.              case INIT3:
  251. #ifdef DEBUG
  252.              printf("\nINIT3:  notxt %d nomnu %d cline %d ixdots %d iydots %d",
  253.               notxt, nomnu, cline, ixdots, iydots);
  254.              printf("\n        graphx %d graphy %d ybias %d modelinl %d",
  255.               graphx, graphy, ybias, modelinl);
  256.              printf("\n        mnuchars %d maxboxes %d hwfill %d hlenab %d",
  257.               mnuchars, maxboxes, hwfill, hlenab);
  258.              printf("\n        graphok %d\n", graphok);
  259. #endif
  260.              outp(CFGREG,3);          /* Enable graphics mode, page1 */
  261.              adswipe();               /* Clear the (invisible) graphics screen */
  262.              gograph();               /* Go to graphics mode. */
  263.              drawbord();              /* Draw the borders */
  264.  
  265.              c.arg1 = 5556;           /* X pixel spacing */
  266.              c.arg2 = 8621;           /* Y pixel spacing */
  267. #ifdef DUMB
  268.              c.arg3 = packbytes(25, 80);
  269. #else
  270.              c.arg3 = 0;
  271. #endif
  272.              break;
  273.  
  274.              case INIT4:
  275.              c.arg1 = 0;              /* No extended functions */
  276. #ifdef SMART
  277.              c.arg2 = EF_SYNC | EF_REDRAW;
  278. #else
  279.              c.arg2 = 0;              /* for now, thanks */
  280. #endif
  281.              break;
  282.  
  283.              case INIT5:
  284.              c.arg1 = iydots;         /* Ymenumax = iydots */
  285.              c.arg2 = YSIZE - 1;      /* iydotsm */
  286.              break;
  287.  
  288.              case TERM:
  289.              break;
  290.  
  291.              case CLEAR:
  292. #ifdef DUMB
  293.              adswipe();
  294.              drawbord();
  295.              c.arg1 = RP_MENU | RP_STAT | RP_SCROLL;
  296. #else
  297.              adsclr();
  298.              c.arg1 = 0;
  299. #endif
  300.              break;
  301.  
  302.              case DOT:
  303.              adsdot(c.arg1, ybias - c.arg2);
  304.              break;
  305.  
  306.              case MOVE:
  307.              lx = c.arg1;
  308.              ly = c.arg2;
  309.              hilight = c.arg3 & 1;
  310.              break;
  311.  
  312.              case DRAW:
  313. #ifdef DUMPCMD
  314.              printf("\nDraw (%d,%d) - (%d,%d) in %d",
  315.               lx, ly, c.arg1, c.arg2, c.arg3);
  316. #endif
  317.              if (c.arg3 >= 0) {
  318.               color = c.arg3;
  319.               adsvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
  320.              } 
  321.              else
  322.              adsxvec(lx, ybias - ly, c.arg1, ybias - c.arg2);
  323.              break;
  324.  
  325.              case FLOOD:
  326.              break;
  327.  
  328.              case MARK:
  329.              case CMARK:
  330.              if (c.arg3 == 0 || c.arg3 == 3) {
  331.               adsmark(c.arg1, ybias - c.arg2);
  332.               c.code = TRUE;
  333.              } 
  334.              else
  335.              c.code = FALSE;
  336.              break;
  337.  
  338.              case CHAR:
  339.              if (tcursx <= (XSIZE-CHARWID))
  340.              adschar(tcursx, tcursy, c.arg1);
  341.              tcursx += CHARWID;
  342.              break;
  343.  
  344.              case ECHAR:
  345.              break;
  346.  
  347.              case MHLITE:
  348.              case MDHLITE:
  349.              for (i = 0, cl = tcursx; i < MCHARS; i++) {
  350.               dsrvid(cl, tcursy);     /* Invert all the characters. */
  351.               cl += CHARWID;
  352.              }
  353.              c.arg1 = FALSE;          /* Say characters not needed */
  354.              break;
  355.  
  356.              case MNUCUR:
  357.              i = (ybias + 1) / c.arg2;
  358.              tcursx = XMENUMIN;
  359.              tcursy = (ybias + 1 - CHARHGT) - (c.arg2 - c.arg1 - 1) * i;
  360.              break;
  361.  
  362.              case TPROMPT:
  363.              break;
  364.  
  365.              case QPLOT:
  366.              break;
  367.  
  368.              case RPEN:
  369.              c.arg1 = 0;
  370.              break;
  371.  
  372.              case GOTEXT:
  373.              gotext();
  374.              break;
  375.  
  376.              case GOTEXTU:
  377.              gotextu();
  378. #ifdef DUMB
  379.              txclr();
  380. #endif
  381.              break;
  382.  
  383.              case GOGRAPH:
  384.              gograph();
  385. #ifdef DUMB
  386.              adswipe();
  387.              c.arg1 = RP_GRAPH | RP_MENU | RP_STAT | RP_SCROLL;
  388. #else
  389.              c.arg1 = 0;
  390. #endif
  391.              break;
  392.  
  393.              case WRSPLIT:
  394.              wrsplit(c.arg1);
  395.              break;
  396.  
  397.              case MODELINE:
  398.              tcursx = tcursy = 0;
  399.              adschar(tcursx, tcursy, 'C');
  400.              tcursx += CHARWID;
  401.              adschar(tcursx, tcursy, c.arg2 + '0'); /* Colour */
  402.              tcursx += CHARWID;
  403.              adschar(tcursx, tcursy, ' ');
  404.              tcursx += CHARWID;
  405.              break;
  406.  
  407.              case COORDL:
  408.              tcursx = XCLINE;
  409.              tcursy = 0;
  410.              break;
  411.  
  412. #ifdef SMART
  413.              case SYNC:
  414.              printf(" <sync> ");
  415.              break;
  416.  
  417.              case REDRAW:
  418.              printf(c.arg1 ? " <clear> " : " <redraw> ");
  419.              c.code = FALSE;
  420.              break;
  421. #endif
  422.  
  423.              default:
  424.              printf("\n** Unimplemented display command code %d **\n",
  425.               c.code);
  426.              c.code = FALSE;
  427.             }
  428.            }
  429.            }
  430.  
  431.            static gograph()
  432.            {
  433.             int cursor, splitbase, i;
  434.             char rch;
  435.  
  436.             modeinit(0x82, graphinit);/* Put the CRTC in graphics mode. */
  437.             if (notxt)                /* Graphics text configured off? */
  438.             return;
  439.  
  440.             /*  Copy the bottom SPLIT lines on the text screen into the text
  441.             area of the graphics screen.  Start by finding address within
  442.             text screen buffer of first character to copy (note that the
  443.             text buffer has two bytes per displayed character).  */
  444.  
  445.             cursor = r6845(14) << 1;  /* Cursor address from CRTC. */
  446.             splitbase = cursor - cursor%160 - ((SPLIT-1)*160);
  447.             if (splitbase < 0) splitbase = 0;
  448.  
  449.             clearsplit();             /* Clear text area on graphics screen. */
  450. #ifndef DUMB
  451.             for (i = splitbase; i < cursor; i += 2) { /* Read character from */
  452.              peek(TEXTSEG, i, &rch, 1);
  453.              wrsplit1(rch);           /* text screen, copy to graphics. */
  454.             }
  455. #endif
  456.            }
  457.  
  458.  
  459.            /*  Go into text mode if not already there, with a clear screen. */
  460.  
  461.            static gotext()
  462.            {
  463.             txclr();
  464.             gotextu();                /* Switch modes. */
  465.            }
  466.  
  467.  
  468.            /*  Go into text mode at user request (show hidden text). */
  469.  
  470.            static gotextu()
  471.            {
  472.             modeinit(0, textinit);    /* Make the mode switch. */
  473.            }
  474.  
  475.  
  476.            /*  Write a character to the graphics screen text area and save it in
  477.                in "hidden" text. */
  478.  
  479.            static wrsplit(c)
  480.            char c;
  481.            {
  482.             wrsplit1(c);
  483. #ifndef DUMB
  484.             putchar(c);               /* Let OS write to hidden screen. */
  485.  
  486. #endif
  487.            }
  488.  
  489.            /*  Write a character to the graphics screen text area. */
  490.  
  491.            static wrsplit1(c)
  492.            char c;
  493.            {
  494.             if (notxt)
  495.             return;                   /* No graphics text area. */
  496.  
  497.             switch (c)  {
  498.              case '\r':               /* Carriage return */
  499.              splitchar = 0;
  500.              break;
  501.              case '\n':               /* Line feed. */
  502.              if (splitdirty)          /* Unless current line is blank, */
  503.              { 
  504.               splitline += CHARHGT;   /*   advance to next. */
  505.               splitdirty = 0;
  506.              }
  507.              break;
  508.              case '\t':               /* tab (does better than DOS!) */
  509.              do
  510.              wrsplit1(' ');
  511.              while (splitchar & 7);
  512.              break;
  513.              case '\b':               /* backspace. */
  514.              if (splitchar > 0)
  515.              splitchar -= CHARWID;
  516.              break;
  517.              default:                 /* Normal character. */
  518.              if (splitchar >= XSIZE)  /* If off end of line, */
  519.              { 
  520.               wrsplit1('\r');         /*   do a line feed. */
  521.               wrsplit1('\n');
  522.              }
  523.              adschar(splitchar, splitline, c); /* Draw it. */
  524.              splitchar += CHARWID;    /* Update cursor. */
  525.              splitdirty = 1;          /* Non-blank line. */
  526.             }
  527.  
  528.             if (splitline >= YSIZE)   /* If off bottom of screen, */
  529.             { 
  530.              hcscroll(SPLIT);         /*   scroll up.  */
  531.              splitline -= CHARHGT;
  532.             }
  533.            }
  534.  
  535.            /*  Initialize the CRTC in a new mode.  ctlbits is the value to be
  536.                put into the CRT control register, and should not include the
  537.                enable-video bit.  */
  538.  
  539.            static modeinit(ctlbits, initstr)
  540.            char ctlbits, *initstr;
  541.            {
  542.             int i;
  543.  
  544.             outp(CTLREG, ctlbits);    /* Disable video signal. */
  545.             for (i = 0; i < INITL; i++) /* Load 6845 registers. */
  546.             { 
  547.              outp(ADRREG, i);         /* Point to reg. #i */
  548.              outp(DATAREG, *initstr++); /* Send it its value. */
  549.             }
  550.  
  551.             for (i = -1; ++i < NSYNC; ) /* Wait until vertical sync */
  552.             { 
  553.              while (~inp(STATREG) & 0x80) ; /*  goes low for the */
  554.              while (inp(STATREG) & 0x80)  ; /*  NSYNCHth time */
  555.             }
  556.             outp(CTLREG, ctlbits | 8);/*   to re-enable video. */
  557.            }
  558.  
  559.            /*  Routine to read a 16-bit CRTC register. */
  560.  
  561.            static unsigned int r6845(r)
  562.            int r;
  563.            {
  564.             char r1, r0;
  565.  
  566.             outp(ADRREG, r++);        /* Point to the register. */
  567.             r1 = inp(DATAREG);        /* Read high byte. */
  568.             outp(ADRREG, r);          /* Point to next register. */
  569.             r0 = inp(DATAREG);        /* Read low byte. */
  570.             return (unsigned int)r0 | ((unsigned int)r1 << 8); /* Return both. */
  571.            }
  572.  
  573.            /*  TXCLR  --  Clear the text screen  */
  574.  
  575.            static txclr()
  576.            {
  577.             /*  Call BIOS to scroll screen clear. */
  578.             ibmbios(VIDEO_IO, SCROLL_UP, 0, 0x184F, 0, 0x700);
  579.  
  580.             /*  Now have it set the cursor to upper left corner. */
  581.             ibmbios(VIDEO_IO, SCURSOR, 0, 0, 0, 0);
  582.            }
  583.  
  584.            /*  DRAWBORD  --  Draw borders on graphics screen  */
  585.  
  586.            static drawbord()
  587.            {
  588.             short i;
  589.  
  590.             /*  Draw the borders  */
  591.  
  592.             color = 7;
  593.             if (!notxt)
  594.             for (i = 0; i-- > -2; )   /* Horizontal */
  595.             adsvec(0, ybias - i, ixdotsm, ybias - i);
  596.  
  597.             if (!nomnu)
  598.             for (i = XMAX; i++ < (XMAX + 2); ) /* Vertical */
  599.             adsvec(i, ybias, i, 0);
  600.            }
  601.  
  602.            /*  Clear the graphics text area and reset its insertion cursor. */
  603.  
  604.            static clearsplit()
  605.            {
  606.             int i;
  607.  
  608. #ifndef DUMB
  609.             for (i=0; i<SPLIT; i++)   /* All these scrolls will */
  610.             hcscroll(SPLIT);          /*    clear the area. */
  611. #endif
  612.  
  613.             /*  Set insertion cursor to SPLIT lines above screen bottom */
  614.             splitchar = 0;
  615.             splitline = YSPLIT;
  616.            }
  617.  
  618.  
  619.